﻿using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using HistogramLr.Models;
using HistogramLr.Properties;

namespace HistogramLr.Views
{
	/// <summary>
	/// MainWindow.xaml の相互作用ロジック
	/// </summary>
	public partial class MainWindow : Window
	{
		private static NLog.Logger log = NLog.LogManager.GetCurrentClassLogger();

		/// <summary>
		/// Constructor.
		/// </summary>
		public MainWindow()
		{
			InitializeComponent();

			// サムネイル上にカーソルを合わせたときの動作
			this.addImageEventHandler(this.imgThumbnail);
			this.addImageEventHandler(this.imgThumbnailB);
			this.addImageEventHandler(this.imgThumbnailG);
			this.addImageEventHandler(this.imgThumbnailR);
		}

		#region サムネイルのMouse処理関連
		/// <summary>
		/// MouseのEventHandler設定.
		/// </summary>
		/// <param name="imgControl"></param>
		private void addImageEventHandler(Image imgControl)
		{
			imgControl.MouseEnter += new MouseEventHandler(imgControl_MouseEnter);
			imgControl.MouseMove += new MouseEventHandler(imgControl_MouseMove);
			imgControl.MouseLeave += new MouseEventHandler(imgControl_MouseLeave);
		}

		/// <summary>
		/// On MouseEnter.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void imgControl_MouseEnter(object sender, MouseEventArgs e)
		{
			this.Cursor = Cursors.Pen;
		}

		/// <summary>
		/// On MouseMove.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void imgControl_MouseMove(object sender, MouseEventArgs e)
		{
			// カーソル場所の色を取得.
			Point p = e.GetPosition((Image)sender);
			Color color = this._pm.Image3.GetThumbColor(p.X, p.Y);

			// UI表示（色とLabel）…透明の場合は描画しない.
			this.rectColor.Fill = new SolidColorBrush(color);
			if (color.A != 0x00)
			{
				double perR = Math.Round((double)color.R * 100 / 0xff, 1);
				double perG = Math.Round((double)color.G * 100 / 0xff, 1);
				double perB = Math.Round((double)color.B * 100 / 0xff, 1);
				this.lblLevelR.Content = string.Format("{0:0.0}", perR);
				this.lblLevelG.Content = string.Format("{0:0.0}", perG);
				this.lblLevelB.Content = string.Format("{0:0.0}", perB);
				this.lblLevelWebRGB.Content = string.Format("#{0:X2}{1:X2}{2:X2}", color.R, color.G, color.B);

				// カラーレベルの表示
				this.imgColorLevel.Source = DrawUtils.DrawColorLevel(color.R, color.G, color.B, this._pm.ColorR, this._pm.ColorG, this._pm.ColorB);
				this.imgColorLevelR.Source = DrawUtils.DrawColorLevel(color.R, this._pm.ColorR);
				this.imgColorLevelG.Source = DrawUtils.DrawColorLevel(color.G, this._pm.ColorG);
				this.imgColorLevelB.Source = DrawUtils.DrawColorLevel(color.B, this._pm.ColorB);
			}
			else
			{
				this.lblLevelR.Content = "0.0";
				this.lblLevelG.Content = "0.0";
				this.lblLevelB.Content = "0.0";
				this.lblLevelWebRGB.Content = "#000000";
			}
		}

		/// <summary>
		/// On MouseLeave.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void imgControl_MouseLeave(object sender, MouseEventArgs e)
		{
			// 色表示を消す.
			this.rectColor.Fill = new SolidColorBrush(Colors.Transparent);
			this.lblLevelR.Content = "0.0";
			this.lblLevelG.Content = "0.0";
			this.lblLevelB.Content = "0.0";
			this.lblLevelWebRGB.Content = "#000000";

			// カラーレベルの非表示
			this.imgColorLevel.Source = DrawUtils.DrawColorLevel(0, this._pm.ColorZero);
			this.imgColorLevelR.Source = DrawUtils.DrawColorLevel(0, this._pm.ColorZero);
			this.imgColorLevelG.Source = DrawUtils.DrawColorLevel(0, this._pm.ColorZero);
			this.imgColorLevelB.Source = DrawUtils.DrawColorLevel(0, this._pm.ColorZero);

			this.Cursor = null;
		}
		#endregion

		/// <summary>
		/// 画像解析用の管理object.
		/// </summary>
		private PhotoManager _pm = new PhotoManager();

		/// <summary>
		/// 初回の描画かどうかのフラグ。
		/// </summary>
		private bool _firstDraw = true;

		/// <summary>
		/// Event handler: 画面初期化後の処理。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void Window_Initialized(object sender, EventArgs e)
		{
			log.Info("Initialized event handler.");
			try
			{
				// コマンドライン引数の取得
				string[] args = Environment.GetCommandLineArgs();
				if (args.Length != 2)
				{
					log.Error("Invalid parameter. Args length = {0}", args.Length);
					MessageBox.Show("Invalid parameter.\nUsage: HistogramLr.exe <Image filename>",
						"Parameter error.", MessageBoxButton.OK, MessageBoxImage.Error);
					return;
				}

				// 画像の解析
				this._pm.LoadImage(args[1]);

				// Labo:
				this.imgHist3D.Source = this._pm.HistogramHS;

				// スケールを設定して描画
				this.resetSliderScaleValue();
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Exception", MessageBoxButton.OK, MessageBoxImage.Error);
				this.showStackTrace(ex);
				this.Close();
			}
			log.Debug("Finished.");
		}

		/// <summary>
		/// Scaleラベルをダブルクリックしたとき（Scaleをデフォルトに戻す）
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void lblScale_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
		{
			this.resetSliderScaleValue();
		}

		/// <summary>
		/// SliderScaleの初期化.
		/// </summary>
		private void resetSliderScaleValue()
		{
			log.Debug("Reset slider scale value.");
			this.sliderScale.Value = Settings.Default.HistogramScalingRatio;
		}

		/// <summary>
		/// Event handler: Slider値の変更。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void sliderScale_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
		{
			if (e.OldValue != e.NewValue)
			{
				// 再描画
				this.drawResult(this.sliderScale.Value);
			}
		}

		/// <summary>
		/// 結果の描画
		/// </summary>
		/// <param name="scale"></param>
		private void drawResult(double scale)
		{
			// 初期化されてない場合は描画スキップ
			if (this._pm == null || !this._pm.Initialized) return;

			// 最初の1回だけ描画する内容
			if (this._firstDraw)
			{
				// 情報の表示
				log.Debug("Drawing information.");
				this.lblFilename.Content = this._pm.FileInformation.Name;
				this.lblFilename.ToolTip = this._pm.FileInformation.FullName;

				// サムネイルの表示
				log.Debug("Drawing thumbnails.");
				this.imgThumbnail.Source = this._pm.Image3.BmpThumbnail;
				this.imgThumbnailB.Source = this._pm.ImageB.BmpThumbnail;
				this.imgThumbnailG.Source = this._pm.ImageG.BmpThumbnail;
				this.imgThumbnailR.Source = this._pm.ImageR.BmpThumbnail;

				this._firstDraw = false;
			}

			// ヒストグラムの描画
			log.Debug("Drawing histogram image. Scale={0}", scale);
			HistogramImageContainer histImageItem = this._pm.DrawHistogramGraph(128, scale);
			this.imgHistogram.Source = histImageItem.Histogram3Graph;
			this.imgHistogramB.Source = histImageItem.HistogramBGraph;
			this.imgHistogramG.Source = histImageItem.HistogramGGraph;
			this.imgHistogramR.Source = histImageItem.HistogramRGraph;

			this.UpdateLayout();
		}

		/// <summary>
		/// デバッグ用StackTrace表示.
		/// </summary>
		/// <param name="ex"></param>
		[Conditional("DEBUG")]
		private void showStackTrace(Exception ex)
		{
			log.Error(ex.StackTrace);
			MessageBox.Show(ex.StackTrace, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
		}
	}
}
